package core

import (
	"context"
	"gopkg.in/olivere/elastic.v5"
	"log"
	"time"
)

type LogInfo interface {
}

type Batch struct {
	Logs []*interface{}
}

type Elastic struct {
	Client    *elastic.Client
	saveChan  chan interface{}
	saveBatch chan *Batch
	index     string
	typeName  string
	BatchLen  int
	Ctx       context.Context
}

var GElastic = make(map[string]*Elastic)

func (e *Elastic) SaveBatch(logs []*interface{}) {
	var (
		err error
	)
	bulk := e.Client.Bulk()

	for _, v := range logs {
		//id := fmt.Sprintf("%d_%d", time.Now().UnixNano(), k)
		//str, _ := json.Marshal(i)

		req := elastic.NewBulkIndexRequest().Index(getIndex(e.index)).Type(e.typeName).Doc(v)
		bulk.Add(req)
	}
	res, err := bulk.Do(e.Ctx)
	if err != nil {
		log.Println(err)
		return
	}
	for _, i := range res.Failed() {
		log.Printf("%#v", i.Error)
	}
}

func (e *Elastic) Save() {
	var (
		batch *Batch
		timer *time.Timer
	)

	for {
		select {
		case tlog := <-e.saveChan:
			if batch == nil {
				batch = &Batch{}
				timer = time.AfterFunc(time.Second, func(bat *Batch) func() {
					return func() {
						e.saveBatch <- bat
					}
				}(batch))
			}

			batch.Logs = append(batch.Logs, &tlog)
			if len(batch.Logs) >= e.BatchLen {
				//log.Printf("batch len,%v", len(batch.Logs))

				e.SaveBatch(batch.Logs)
				batch = nil
				timer.Stop()
			}
		case blogs := <-e.saveBatch:
			if blogs != batch {
				continue //说明已经提交过
			}
			log.Println("timeout...", len(blogs.Logs))
			e.SaveBatch(blogs.Logs)
			batch = nil

		}
	}

}

func (e *Elastic) AddTask(info interface{}) {
	e.saveChan <- info
}

func (e *Elastic) DelIndex() {
	tc := time.Tick(time.Minute * 10)
	for {
		date := time.Now().AddDate(0, 0, -15).Format("2006.01.02")
		delIndex := e.index + "-" + date
		_, res := e.Client.DeleteIndex(delIndex).Do(context.TODO())
		log.Println("del", delIndex, res)
		<-tc

	}

}
func (e *Elastic) GetData(index string) {


}
func getIndex(index string) string {
	date := time.Now().Format("2006.01.02")
	return index + "-" + date
}

func InitElastic(ctx context.Context, Addrs []string, index string) (e *Elastic, err error) {
	batchLen := 100
	client, err := elastic.NewClient(elastic.SetURL(Addrs...), elastic.SetSniff(false))
	if err != nil {
		log.Panicln(err)
	}
	e = &Elastic{
		Client:    client,
		index:     index,
		typeName:  "doc",
		saveChan:  make(chan interface{}, batchLen),
		saveBatch: make(chan *Batch, batchLen),
		Ctx:       ctx,
		BatchLen:  batchLen,
	}
	GElastic[index] = e
	go GElastic[index].Save()
	go GElastic[index].DelIndex()

	return
}
